home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / jaq / dist / ttime.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-01  |  10.5 KB  |  476 lines

  1. /* 
  2.  * ttime.c --
  3.  *
  4.  *    time conversion utilities
  5.  *
  6.  * Copyright 1992 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  *
  15.  * Quote:
  16.  *      "A moment's thought would have shown him,
  17.  *       but a moment is a long time and thought 
  18.  *       is a painful process."
  19.  *       -- A. E. Housman
  20.  */
  21.  
  22. #ifndef lint
  23. static char rcsid[] = "$Header: /sprite/lib/forms/RCS/ttime.c,v 1.0 91/01/07 18:02:37 mottsmth Exp $ SPRITE (Berkeley)";
  24. #endif /* not lint */
  25.  
  26. #include "jaquith.h"
  27.  
  28. #define T_DATELEN 21
  29. #define DATESEPARATORS "/-"
  30. #define TIMESEPARATORS ".:"
  31. #define SECONDSPERDAY 60*60*24
  32.  
  33. static int ValidateDateParts _ARGS_ ((char *dateStr, struct tm *partsPtr));
  34. static int ValidateTimeParts _ARGS_ ((char *timeStr, struct tm *partsPtr));
  35.  
  36. static int daysPerMonth[] = 
  37.     { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  38. static char *months[] = {
  39.     "january",   "february", "march",    "april",
  40.     "may",       "june",     "july",     "august",
  41.     "september", "october",  "november", "december" };
  42.  
  43.  
  44.  
  45.  
  46. /*
  47.  *----------------------------------------------------------------------
  48.  *
  49.  * Time_Stamp --
  50.  *
  51.  *    Return time-of-day stamp in milliseconds.
  52.  *
  53.  * Results:
  54.  *    time stamp
  55.  *
  56.  * Side effects:
  57.  *    none.
  58.  *
  59.  *----------------------------------------------------------------------
  60.  */
  61.  
  62. long
  63. Time_Stamp()
  64. {
  65.     struct timeval curTime;
  66.  
  67.     gettimeofday(&curTime, NULL);
  68.     curTime.tv_sec % (LONG_MAX/2);
  69.     return (curTime.tv_sec*1000) + (curTime.tv_usec/1000);
  70. }
  71.  
  72.  
  73. /*
  74.  *----------------------------------------------------------------------
  75.  *
  76.  * Time_CvtToString --
  77.  *
  78.  *    Convert internal format to printable form
  79.  *
  80.  * Results:
  81.  *    static char string. If year is current then include
  82.  *      time in string, else include year instead (a la 'ls' cmd)..
  83.  *
  84.  * Side effects:
  85.  *    none.
  86.  *
  87.  *----------------------------------------------------------------------
  88.  */
  89.  
  90. char *
  91. Time_CvtToString(timePtr)
  92.     time_t *timePtr;          /* time object to be made printable */
  93. {
  94.     struct UnixTimeStr {
  95.     char dayOfWeek[4];
  96.     char month[4];
  97.     char day[3];
  98.     char time[9];
  99.     char year[4];
  100.     char cr;
  101.     char null;
  102.     } *timeStr;
  103.     char curYear[5];
  104.     time_t curTime;
  105.  
  106.     curTime = Time_GetCurDate();
  107.     timeStr = (struct UnixTimeStr *) ctime(&curTime);
  108.     strcpy(curYear, timeStr->year);
  109.  
  110.     timeStr = (struct UnixTimeStr *) ctime(timePtr);
  111.     timeStr->cr = '\0';
  112.  
  113.     if (strncmp(curYear, timeStr->year, 4) != 0) {
  114.     strcpy(timeStr->time, timeStr->year);
  115.     strcpy(timeStr->time+4, "    ");
  116.     } else {
  117.     timeStr->time[8] = '\0';
  118.     }
  119.  
  120.     return timeStr->month;
  121.  
  122. }
  123.  
  124.  
  125. /*
  126.  *----------------------------------------------------------------------
  127.  *
  128.  * Time_Compare --
  129.  *
  130.  *    Compare 2 dates for equality.
  131.  *
  132.  * Results:
  133.  *    <1, 0, >0
  134.  *
  135.  * Side effects:
  136.  *    none.
  137.  *
  138.  *----------------------------------------------------------------------
  139.  */
  140.  
  141. int
  142. Time_Compare(time1, time2, dateOnly)
  143.     time_t time1;             /* time object1 */
  144.     time_t time2;             /* time object2 */
  145.     int dateOnly;             /* 1 == round off the time to day units */
  146. {
  147.     if (dateOnly) {
  148.     time1 -= (time1 % SECONDSPERDAY);
  149.     time2 -= (time2 % SECONDSPERDAY);
  150.     }
  151.  
  152.     return ((unsigned)time1-(unsigned)time2);
  153. }
  154.  
  155.  
  156.  
  157. /*
  158.  *----------------------------------------------------------------------
  159.  *
  160.  * Time_GetCurDate --
  161.  *
  162.  *    Calculate current date/time including zone offset.
  163.  *
  164.  * Results:
  165.  *    One long word giving # secs since 1 Jan 1970 GMT.
  166.  *
  167.  * Side effects:
  168.  *    none.
  169.  *
  170.  *----------------------------------------------------------------------
  171.  */
  172.  
  173. time_t
  174. Time_GetCurDate()
  175. {
  176.     struct timeval  curTime;
  177.     struct timezone curZone;
  178.     long time;
  179.  
  180.     gettimeofday(&curTime, &curZone);
  181.     time = curTime.tv_sec;
  182.  
  183. /*    fprintf(stderr,"GetCurDate: %s\n", ctime(&time));*/
  184.     return (time);
  185. }
  186.  
  187.  
  188. /*
  189.  *----------------------------------------------------------------------
  190.  *
  191.  * getindate --
  192.  *
  193.  *    Convert a date-time string into Unix internal format.
  194.  *
  195.  * Results:
  196.  *    none.
  197.  *
  198.  * Side effects:
  199.  *    none.
  200.  *
  201.  * Note: This whole thing is a hack. Daylight savings time is not
  202.  *      accounted for.  The attempt is to save the number of seconds
  203.  *      since 1 Jan 1970 0:0:0 GMT.
  204.  *
  205.  *      Collyer and Moraes (U. of Toronto) have written a much more
  206.  *      thorough package but I can't find it and don't know if I could
  207.  *      distribute it even if I had it. I've adhered to their interface
  208.  *      (including not capitalizing the procedure names) so that 
  209.  *      you can plug their stuff in and get better parsing.
  210.  *
  211.  *      Too bad not all systems have SYSV's getdate() routine.
  212.  *
  213.  *----------------------------------------------------------------------
  214.  */
  215.  
  216. int
  217. getindate(dateStr, timebPtr)
  218.     char *dateStr;            /* incoming date in string form */
  219.     struct timeb *timebPtr;   /* result structure */
  220. {
  221.     char *timeStr;
  222.     int retCode = T_SUCCESS;
  223.     struct timeval curTime;
  224.     struct tm *curTimePtr;
  225.     struct tm curTimeParts;
  226.     time_t *timePtr = &timebPtr->time;
  227.  
  228.     gettimeofday(&curTime, (struct timezone *)NULL);
  229.     curTimePtr = localtime((time_t *)&curTime.tv_sec);
  230.     curTimePtr->tm_isdst = -1;
  231.     curTimeParts = *curTimePtr;
  232.  
  233.     if (dateStr == (char *)NULL) {
  234.     return T_FAILURE;
  235.     }
  236.  
  237.     dateStr = (char *)strtok(dateStr, TIMESEPARATORS);
  238.  
  239.     if (dateStr == (char *)NULL) {
  240.     return T_FAILURE;
  241.     }
  242.  
  243.     timeStr = (char *)strtok((char *)NULL, ".");
  244.  
  245.     retCode = ValidateDateParts(dateStr, &curTimeParts);
  246.     if (retCode == T_SUCCESS) {
  247.     retCode = ValidateTimeParts(timeStr, &curTimeParts);
  248.     }
  249.  
  250.     if (retCode == T_SUCCESS) {
  251.     *timePtr = mktime(&curTimeParts);
  252.     }
  253.  
  254.     return retCode;
  255.  
  256. }
  257.  
  258.  
  259. /*
  260.  *----------------------------------------------------------------------
  261.  *
  262.  * getindatepair --
  263.  *
  264.  *    Convert a pair of date-time strings into Unix internal format.
  265.  *
  266.  * Results:
  267.  *    none.
  268.  *
  269.  * Side effects:
  270.  *    none.
  271.  *
  272.  *----------------------------------------------------------------------
  273.  */
  274.  
  275. int
  276. getindatepair(dateStr, timebPtr1, timebPtr2)
  277.     char *dateStr;            /* incoming date in string form */
  278.     struct timeb *timebPtr1;  /* result structures */
  279.     struct timeb *timebPtr2;
  280. {
  281.     char *ptr1, *ptr2;
  282.  
  283.     if (dateStr == (char *)NULL) {
  284.     return T_FAILURE;
  285.     }
  286.  
  287.     ptr1 = (char *)strtok(dateStr, ",");
  288.     if (ptr1 == (char *)NULL) {
  289.     return T_FAILURE;
  290.     }
  291.  
  292.     ptr2 = (char *)strtok((char *)NULL, ",");
  293.     if (ptr2 == (char *)NULL) {
  294.     return T_FAILURE;
  295.     }
  296.  
  297.     if (getindate(ptr1, timebPtr1) == T_SUCCESS) {
  298.     return getindate(ptr2, timebPtr2);
  299.     }
  300.     
  301.     return T_FAILURE;
  302. }
  303.  
  304.  
  305. /*
  306.  *----------------------------------------------------------------------
  307.  *
  308.  * ValidateDateParts --
  309.  *
  310.  *      Check and convert date pieces
  311.  *
  312.  * Results:
  313.  *    Return Code.
  314.  *
  315.  * Side effects:
  316.  *    none.
  317.  *
  318.  * Note: To simplify parsing, we only accept dates of the forms:
  319.  *                  dd-month (or) dd-month-yy
  320.  *       where dd, yy are integers and month is a char string.
  321.  *
  322.  *----------------------------------------------------------------------
  323.  */
  324.  
  325. static int
  326. ValidateDateParts(dateStr, partsPtr)
  327.     char *dateStr;            /* date with time stripped off */
  328.     struct tm *partsPtr;      /* structure to receive parts */
  329. {
  330.     int i;
  331.     int length;
  332.     int count = 0;
  333.     char *dateParts[3];
  334.     int leapYear = 0;
  335.     int day;
  336.     int month;
  337.     int year;
  338.  
  339.     if ((dateParts[0]=(char *)strtok(dateStr, DATESEPARATORS)) !=
  340.     (char *)NULL) {
  341.     count++;
  342.     if ((dateParts[1]=(char *)strtok(NULL, DATESEPARATORS)) !=
  343.         (char *)NULL) {
  344.         count++;
  345.         if ((dateParts[2]=(char *)strtok(NULL, DATESEPARATORS)) !=
  346.         (char *)NULL) {
  347.         count++;
  348.         }
  349.     }
  350.     }
  351.  
  352.     if ((count < 2) || (count > 3) || (strlen(dateParts[1]) < 3)) {
  353.     return T_FAILURE;
  354.     }
  355.     
  356.     /* verify year */
  357.     /* Note: 68 years = MAXDECINT seconds / (60 * 60 * 24 * 7 * 52) */
  358.     if (count > 2) {
  359.     if (Utils_CvtInteger(dateParts[2], 1970, 1970+68, &year) != T_SUCCESS) {
  360.         return T_FAILURE;
  361.     }
  362.     } else {
  363.     year = partsPtr->tm_year + 1900;
  364.     }
  365.     if ((year % 4 == 0) &&
  366.     ((year % 100 != 0) || (year % 400 == 0))) {
  367.     leapYear = 1;
  368.     }
  369.  
  370.     /* verify month */
  371.     length = strlen(dateParts[1]);
  372.     partsPtr->tm_yday = -1;
  373.     for (i=0; i<12; i++) {
  374.     if ((length <= strlen(months[i])) &&
  375.         (strncasecmp(dateParts[1], months[i], length) == 0)) {
  376.         month = i;
  377.         break;
  378.     }
  379.     partsPtr->tm_yday += daysPerMonth[i];
  380.     }
  381.     if (i >= 12) {
  382.     return T_FAILURE;
  383.     }
  384.  
  385.     /* verify day */
  386.     if (Utils_CvtInteger(dateParts[0], 0, daysPerMonth[month], &day) !=
  387.     T_SUCCESS) {
  388.     return T_FAILURE;
  389.     }
  390.     if ((day == 29) && (month == 1) && (!leapYear)) {
  391.     return T_FAILURE;
  392.     }
  393.     partsPtr->tm_mday = day;
  394.     partsPtr->tm_yday += day;
  395.     if ((month > 1) && (!leapYear)) {
  396.     partsPtr->tm_yday -= 1;
  397.     }
  398.     partsPtr->tm_year = year - 1900;
  399.     partsPtr->tm_mon = month;
  400.     partsPtr->tm_wday = (partsPtr->tm_yday + partsPtr->tm_year - 1) % 7;
  401.  
  402.     return T_SUCCESS;
  403. }
  404.  
  405.  
  406.  
  407. /*
  408.  *----------------------------------------------------------------------
  409.  *
  410.  * ValidateTimeParts --
  411.  *
  412.  *      Check and convert time pieces
  413.  *
  414.  * Results:
  415.  *    Return Code.
  416.  *
  417.  * Side effects:
  418.  *    none.
  419.  *
  420.  * Note: To simplify parsing, we only accept times of the forms:
  421.  *       hh[-mm[-ss]]
  422.  *
  423.  *----------------------------------------------------------------------
  424.  */
  425.  
  426. static int
  427. ValidateTimeParts(timeStr, partsPtr)
  428.     char *timeStr;            /* time with date stripped off */
  429.     struct tm *partsPtr;      /* structure to receive parts */
  430. {
  431.     char *timeParts[3];
  432.     int count = 0;
  433.     
  434.     partsPtr->tm_hour = 0;
  435.     partsPtr->tm_min = 0;
  436.     partsPtr->tm_sec = 0;
  437.  
  438.     if (timeStr == (char *)NULL) {
  439.     return T_SUCCESS;
  440.     }
  441.  
  442.     if ((timeParts[0]=(char *)strtok(timeStr, TIMESEPARATORS)) !=
  443.     (char *)NULL) {
  444.     count++;
  445.     if ((timeParts[1]=(char *)strtok(NULL, TIMESEPARATORS)) !=
  446.         (char *)NULL) {
  447.         count++;
  448.         if ((timeParts[2]=(char *)strtok(NULL, TIMESEPARATORS)) !=
  449.         (char *)NULL) {
  450.         count++;
  451.         }
  452.     }
  453.     }
  454.  
  455.     if ((count < 1) || (count > 3)) {
  456.     return T_FAILURE;
  457.     }
  458.  
  459.     if (count > 2) {
  460.     if (Utils_CvtInteger(timeParts[2], 0, 59, &partsPtr->tm_sec) != T_SUCCESS) {
  461.         return T_FAILURE;
  462.     }
  463.     }
  464.  
  465.     if (count > 1) {
  466.     if (Utils_CvtInteger(timeParts[1], 0, 59, &partsPtr->tm_min) != T_SUCCESS) {
  467.         return T_FAILURE;
  468.     }
  469.     }
  470.  
  471.     return (Utils_CvtInteger(timeParts[0], 0, 23, &partsPtr->tm_hour));
  472.  
  473. }
  474.  
  475.  
  476.